package org.example.sort.type;

import java.util.Comparator;

/**
 * 类描述：排序抽象公共类
 * <br>
 *
 * @author ZS
 * @version 1.0
 * @date 2020/12/28
 **/
@SuppressWarnings("unchecked")
public abstract class AbstractSort<E> implements Comparable<AbstractSort<E>> {
    protected E[] elements;
    protected int cmpCount;
    protected int swapCount;
    protected long time;

    /**
     * 泛型E要么继承Comparable，要么自定义比较器
     */
    protected Comparator<E> comparator;

    public AbstractSort() {
        this(null);
    }

    public AbstractSort(Comparator<E> comparator) {
        this.comparator = comparator;
    }

    public AbstractSort<E> sort(E[] elements) {
        this.elements = elements;

        /**
         * 当elements不为null而且length > 1时才需要进行排序
         */
        if (needSort()) {
            long start = System.currentTimeMillis();
            E[] ans = sort();
            time = System.currentTimeMillis() - start;
        }
        return this;
    }

    /**
     * 具体的排序函数
     *
     * @return
     */
    protected abstract E[] sort();

    /**
     * 元素比较的方法
     *
     * @param e1
     * @param e2
     * @return 相等，返回0；e1>e2，返回正数；e1<e2，返回负数
     */
    protected int compare(E e1, E e2) {
        cmpCount++;
        // 元素比较，如果定义了比较器，则使用比较器
        if (comparator != null) {
            return comparator.compare(e1, e2);
        }
        // 比较的对象必须实现Comparable接口
        return ((Comparable<E>) e1).compareTo(e2);
    }

    protected boolean blank() {
        return null == elements || elements.length == 0;
    }

    protected boolean notBlank() {
        return !blank();
    }

    protected boolean needSort() {
        return null != elements && elements.length > 1;
    }

    /**
     * 交换元素的值
     *
     * @param e1
     * @param e2
     */
    protected void swap(int e1, int e2) {
        swapCount++;

        E tmp = elements[e1];
        elements[e1] = elements[e2];
        elements[e2] = tmp;
    }

    protected AbstractSort<E> printArray() {
        StringBuilder builder = new StringBuilder();
        builder.append("[")
                .append(getClass().getSimpleName())
                .append("]")
                .append("\n")
                .append("size = ")
                .append(elements.length)
                .append("\n")
                .append("[");
        for (E element : elements) {
            builder.append(element).append(", ");
        }
        builder.append("]");
        System.out.println(builder.toString());
        return this;
    }

    /**
     * 继承Comparable接口，实现compareTo方法，用于对各个排序算法
     * 根据用时进行排序
     *
     * @param o
     * @return
     */
    @Override
    public int compareTo(AbstractSort<E> o) {
        return (int) (this.time - o.time);
    }

    // 方便打印
    protected String easyPrint(int n) {
        if (n < 10000) {
            return String.valueOf(n);
        }
        if (n < 100000000) {
            return n / 10000 + "万";
        }
        return n / 100000000 + "亿";
    }

    @Override
    public String toString() {
        String timeStr = "耗时：" + (time / 1000) + "s(" + time + "ms)";
        String compareCount = "比较：" + easyPrint(cmpCount);
        String swap = "交换：" + easyPrint(swapCount);
        return "[" + getClass().getSimpleName() + "]\n"
                + timeStr + "\n"
                + compareCount + "\n"
                + swap + "\n";
    }
}

